package com.orderplus.opshop.core.template;

import com.orderplus.opshop.common.util.RequestLogUtils;
import com.orderplus.opshop.core.constants.enums.ResponseCodeConstant;
import com.orderplus.opshop.core.data.request.BaseRequest;
import com.orderplus.opshop.core.data.request.RequestParam;
import com.orderplus.opshop.core.data.response.ResponseData;
import com.orderplus.opshop.core.exception.CommonException;
import com.orderplus.opshop.core.exception.ParamErrorException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.dao.DuplicateKeyException;

import javax.validation.ConstraintViolationException;

/**
 * author:maihj 2018.9.21
 *
 * @param <REQ>         原来的请求
 * @param <Result>      原来的响应
 * @param <TransReq>    转换后的请求
 * @param <TransResult> 转换后的响应
 */
@Slf4j
public abstract class TransTemplate<REQ extends BaseRequest, Result, TransReq, TransResult extends ResponseData<RESP>, RESP> {

	public ResponseData<Result> callInner(RequestParam<REQ> req) {
		ResponseData<Result> response = new ResponseData<>();
		try {
			TransReq transReq = transformRequest(req.getRequestBody());
			RequestParam<TransReq> RequestParam = new RequestParam<>();
			RequestParam.setChannelCode(req.getChannelCode());
			RequestParam.setTraceId(RequestLogUtils.getCurTraceId(req));
			RequestParam.setOperLevel(RequestLogUtils.getCurOperLevel(req));
			RequestParam.setAppName(req.getAppName());
			RequestParam.setRequestBody(transReq);
			TransResult transResp = call(RequestParam);
			response.setCode(transResp.getCode());
			response.setMsg(transResp.getMsg());
			if (transResp.getData() != null) {
				response.setData(transformerResponse(transResp.getData(), req));
			}
		} catch (ConstraintViolationException e) {
			ConstraintViolationException cvException = (ConstraintViolationException) e;
			log.error("ConstraintViolationException错误,类:[{}],异常:", this.getClass().getName(), e);
			response.setCode(ResponseCodeConstant.REQUEST_ILLEGAL.getResponseCode());
			response.setMsg(ExceptionUtils.getMessage(cvException));
		} catch (ParamErrorException e) {
			log.error("ParamErrorException错误,类:[{}],异常:", this.getClass().getName(), e);
			response.setCode(e.getCode());
			response.setMsg(e.getMessage());
		} catch (CommonException e) {
			log.error("CommonException错误,类:[{}],异常:", this.getClass().getName(), e);
			response.setCode(e.getCode());
			response.setMsg(e.getMessage());
		} catch (DuplicateKeyException e) {
			log.error("DuplicateKeyException错误,类:[{}],异常:", this.getClass().getName(), e);
			response.setCode(ResponseCodeConstant.DB_EXCEPTION.getResponseCode());
			response.setMsg("存在不可重复数据:" + e.getCause().getMessage());
		} catch (Exception e) {
			log.error("Exception错误,类:[{}],异常:", this.getClass().getName(), e);
			response.setCode(ResponseCodeConstant.SYS_EXCEPTION.getResponseCode());
			response.setMsg(ResponseCodeConstant.SYS_EXCEPTION.getResponseDesc());
		}
		return response;
	}

	/* 转换后的调用,跟响应 */
	protected abstract TransResult call(RequestParam<TransReq> req);

	/* 将请求对象进行转换 */
	protected abstract TransReq transformRequest(REQ req);

	/* 将结果对象进行转换 */
	protected abstract Result transformerResponse(RESP resp, RequestParam<REQ> req);

}
